package com.kystar.muxplayer.selfview;

import android.annotation.SuppressLint;
import android.content.Context;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Rect;
import android.os.Build.VERSION;
import android.os.Build.VERSION_CODES;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.util.AttributeSet;
import android.util.SparseArray;
import android.view.MotionEvent;
import android.view.PointerIcon;
import android.view.View;
import android.widget.FrameLayout;

import com.kystar.muxplayer.BaseApp;
import com.kystar.muxplayer.R;
import com.kystar.muxplayer.base.TLog;
import com.kystar.muxplayer.base.TDevice;
import com.kystar.muxplayer.model.Bound;
import com.kystar.muxplayer.model.Layer;
import com.kystar.muxplayer.protocol.code.set.CS0E_LayerInfo;
import com.kystar.muxplayer.protocol.code.set.CS0FLayerParam;

import junit.framework.TestResult;

/**
 * Created by peanut on 2018/8/14
 */
public class PvmFrameLayout extends FrameLayout {

    float radius = 15f;
    View selectView;
    int selectIndex;
    int frameWidth, frameHeight;
    float strokeWidth = 2f;
    Paint yellowPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
    Paint redPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
    Paint gBluePaint = new Paint(Paint.ANTI_ALIAS_FLAG);
    Paint grayPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
    Paint dotPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
    Paint whitePaint = new Paint(Paint.ANTI_ALIAS_FLAG);
    Paint horPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
    Paint vectPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
    Paint textPaint = new Paint(Paint.ANTI_ALIAS_FLAG);


    private static final int BORDER_SELECT_NONE = -1;
    private static final int BORDER_SELECT_LEFT = 0;
    private static final int BORDER_SELECT_LEFT_TOP = 1;
    private static final int BORDER_SELECT_TOP = 2;
    private static final int BORDER_SELECT_RIGHT_TOP = 3;
    private static final int BORDER_SELECT_RIGHT = 4;
    private static final int BORDER_SELECT_RIGHT_BOTTOM = 5;
    private static final int BORDER_SELECT_BOTTOM = 6;
    private static final int BORDER_SELECT_LEFT_BOTTOM = 7;
    private static final int BORDER_SELECT_MIDDLE = 8;

    int currentSelect = BORDER_SELECT_NONE;

    Layer[] mLayers;

    public Layer[] getLayers() {
        return mLayers;
    }

    public void setLayers(Layer[] layers) {
        mLayers = layers;
    }

    public int getSelectIndex() {
        return selectIndex;
    }

    public void setSelectIndex(int selectIndex) {
        this.selectIndex = selectIndex;
        invalidate();
    }

    public View getSelectView() {
        return selectView;
    }

    public void setSelectView(View selectView) {
        this.selectView = selectView;
        invalidate();
    }

    public PvmFrameLayout(@NonNull Context context) {
        super(context);
        init();
    }

    public PvmFrameLayout(@NonNull Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
        init();

    }

    public PvmFrameLayout(@NonNull Context context, @Nullable AttributeSet attrs,
                          int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init();

    }

    public PvmFrameLayout(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr,
                          int defStyleRes) {
        super(context, attrs, defStyleAttr, defStyleRes);
        init();
    }

    @SuppressLint("ResourceType")
    @Override
    public PointerIcon onResolvePointerIcon(MotionEvent event, int pointerIndex) {
        if (VERSION.SDK_INT >= VERSION_CODES.N) {
            return PointerIcon.load(getResources(),
                    R.drawable.ic_drop_down);//super.onResolvePointerIcon(event, pointerIndex);
        }
        return super.onResolvePointerIcon(event, pointerIndex);
    }

    private void init() {
        yellowPaint.setStyle(Paint.Style.STROKE);//空心矩形框
        yellowPaint.setColor(getResources().getColor(R.color.pvw_layer_border_color_normal));
        yellowPaint.setStrokeWidth(strokeWidth);

        redPaint.setStyle(Paint.Style.STROKE);//空心矩形框
        redPaint.setColor(getResources().getColor(R.color.pvw_layer_border_color_selected));
        redPaint.setStrokeWidth(strokeWidth);

        grayPaint.setStyle(Paint.Style.STROKE);//空心矩形框
        grayPaint.setColor(Color.RED);
        grayPaint.setStrokeWidth(strokeWidth);

        gBluePaint.setColor(0xff0D3A54);
        gBluePaint.setStyle(Paint.Style.FILL);//设置填满

        dotPaint.setColor(0xff0D3A54);

        whitePaint.setColor(Color.WHITE);

        horPaint.setColor(Color.BLUE);
        horPaint.setStrokeWidth(strokeWidth);

        vectPaint.setColor(Color.BLUE);
        vectPaint.setStrokeWidth(strokeWidth);

        textPaint.setColor(getResources().getColor(R.color.main_font_color_normal));
        textPaint.setTextSize(15);
        textPaint.setStrokeWidth(1.0f);
    }

    @Override
    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
        super.onSizeChanged(w, h, oldw, oldh);
        frameWidth = w;
        frameHeight = h;
    }


    @Override
    protected void dispatchDraw(Canvas canvas) {
        super.dispatchDraw(canvas);
        drawRectangle(canvas);
        if(!isLock) {
            drawCircle(canvas);
            drawLine(canvas);
        }
    }

    private void drawLine(Canvas canvas) {
        if (horLine.needDraw()) {
            canvas.drawLine(horLine.key, topPadding, horLine.key, frameHeight - bottomPadding,
                    horPaint);
        }
        if (vectLine.needDraw()) {
            canvas.drawLine(leftPadding, vectLine.key, frameWidth - rightPadding, vectLine.key,
                    vectPaint);
        }
    }

    private void drawForeground(Canvas canvas, View view, boolean select) {
        Bound bound = BaseApp.toWorld(new Bound(view.getLeft(), view.getTop(), view.getWidth(), view.getHeight()), getWidth(), getHeight());
//        canvas.drawRect(left, top, left + width, top + height, gBluePaint);//todo need draw text
        Layer layer = (Layer) view.getTag();

        int x = view.getLeft() + 10;
        int y = view.getTop() + 20;
        canvas.drawText(layer.getLayerType().name, x, y, textPaint);
        int padding = 35;
        canvas.drawText(": " + layer.getSourceType().name, x + padding, y, textPaint);
        y += 15;
        canvas.drawText("Pos", x, y, textPaint);
        canvas.drawText(": " + bound.x + "," + bound.y, x + padding, y, textPaint);
        y += 15;
        canvas.drawText("Size", x, y, textPaint);
        canvas.drawText(": " + bound.w + "x" + bound.h, x + padding, y, textPaint);

//        canvas.drawRect(left, top, left + width, top + height, yellowPaint);
//        if (select) {
//            canvas.drawRect(left, top, left + width, top + height, redPaint);
//        }


    }

    private void drawRectangle(Canvas canvas) {
        int left, top, right, bottom;
        for (int i = 0; i < getChildCount(); i++) {
            View view = getChildAt(i);
            left = view.getLeft();
            top = view.getTop();
            right = view.getRight();
            bottom = view.getBottom();
            //     TLog.e("i",i,"left",left,"top",top,"right","right",right,"bottom",bottom);
            if (view.getVisibility() == VISIBLE) {
                canvas.drawRect(left, top, right, bottom, yellowPaint);
                if(isShowInfo) {
                    drawForeground(canvas, view, false);
                }
            }
        }
        if (getSelectView() != null && getSelectView().getVisibility() == VISIBLE) {
            View view = getSelectView();
            left = view.getLeft();
            top = view.getTop();
            right = view.getRight();
            bottom = view.getBottom();
            if(!isLock) {
                canvas.drawRect(left, top, right, bottom, redPaint);
            }
           // drawForeground(canvas, view, true);
        }
    }

    private void drawCircle(Canvas canvas) {
        if (getSelectView() == null || getSelectView().getVisibility() != VISIBLE) {
            //  TLog.e("selectView is null");
            return;
        } else {
            //  TLog.e("selectView is not null");
        }
        View selectView = getSelectView();
        int left, top, right, bottom, width, height;
        left = selectView.getLeft();
        top = selectView.getTop();
        right = selectView.getRight();
        bottom = selectView.getBottom();
        width = right - left;
        height = bottom - top;
        drawTouchDot(left, top + height / 2, canvas);
        drawTouchDot(left, top, canvas);
        drawTouchDot(left + width / 2, top, canvas);
        drawTouchDot(right, top, canvas);
        drawTouchDot(right, top + height / 2, canvas);
        drawTouchDot(right, bottom, canvas);
        drawTouchDot(left + width / 2, bottom, canvas);
        drawTouchDot(left, bottom, canvas);
    }

    private void drawTouchDot(int x, int y, Canvas canvas) {
        //   canvas.drawCircle(x, y, radius, whitePaint);
        canvas.drawCircle(x, y, radius  / 3, dotPaint);
    }

//    int dStartX, dStartY;

//    @Override
//    public boolean onInterceptTouchEvent(MotionEvent ev) {
//        super.onInterceptTouchEvent(ev);
//        boolean intercepted = false;
//        switch (ev.getAction()) {
//            case MotionEvent.ACTION_DOWN:
//                intercepted = false;
//                dStartX = (int) ev.getX();
//                dStartY = (int) ev.getY();
//                onTouchEvent(ev);
//                break;
//            case MotionEvent.ACTION_MOVE:
//                int moveX = (int) ev.getX();
//                int moveY = (int) ev.getY();
//                int dx = moveX - dStartX;
//                int dy = moveY - dStartY;
//                if (dx != 0 && dy != 0) intercepted = true;
//                break;
//            case MotionEvent.ACTION_UP:
//                intercepted = false;
//                break;
//        }
//        return intercepted;
//    }

    private int left, top, right, bottom;
    private int tLeft, tTop, tRight, tBottom;
    private int dx, dy;
    int lastX, lastY;
    int MIN_WIDTH = 150;
    int MIN_HEIGHT = 100;
    int leftPadding = 0;
    int rightPadding = 0;
    int topPadding = 0;
    int bottomPadding = 0;

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        if(isLock) return super.onTouchEvent(event);
        View currentSelectView = getSelectView();
        int action = event.getAction();
        if (currentSelectView == null && action != MotionEvent.ACTION_DOWN) {
            return super.onTouchEvent(event);
        }

        switch (action) {
            case MotionEvent.ACTION_DOWN:
                lastX = (int) event.getRawX();
                lastY = (int) event.getRawY();
                float x = event.getX();
                float y = event.getY();

                if (currentSelectView != null) {
                    currentSelect = motionEventSelect(x, y, currentSelectView);
                }
                if (currentSelect == BORDER_SELECT_NONE) {//重新计算选择位置
                    for (int i = getChildCount() - 1; i >= 0; i--) {
                        View view = getChildAt(i);
                        if (view == currentSelectView) {
                            continue;
                        }
                        currentSelect = motionEventSelect(x, y, view);
                        if (currentSelect != BORDER_SELECT_NONE) {
                            setSelectView(view);
                            currentSelectView = view;
                            setSelectIndex(i);
                            break;
                        }
                    }
                }
                if (currentSelectView != null) {
                    tLeft = left = currentSelectView.getLeft();
                    tTop = top = currentSelectView.getTop();
                    tRight = right = currentSelectView.getRight();
                    tBottom = bottom = currentSelectView.getBottom();

                    initSparseArray();
                }

                break;
            case MotionEvent.ACTION_MOVE:
                dx = (int) event.getRawX() - lastX;
                dy = (int) event.getRawY() - lastY;
                switch (currentSelect) {
                    case BORDER_SELECT_LEFT: {//zuozhong
                        tLeft = left + dx;
                        if (tLeft < leftPadding) {
                            tLeft = leftPadding;
                        } else if (tRight - tLeft < MIN_WIDTH) {
                            tLeft = tRight - MIN_WIDTH;
                        } else {
                            tLeft = parseMagnetHor(tLeft);
                        }
                    }
                    break;
                    case BORDER_SELECT_LEFT_TOP: {
                        tLeft = left + dx;
                        if (tLeft - leftPadding < 0) {
                            tLeft = leftPadding;
                        } else if (tRight - tLeft < MIN_WIDTH) {
                            tLeft = tRight - MIN_WIDTH;
                        } else {
                            tLeft = parseMagnetHor(tLeft);
                        }
                        tTop = top + dy;
                        if (tTop - topPadding < 0) {
                            tTop = topPadding;
                        } else if (tBottom - tTop < MIN_WIDTH) {
                            tTop = tBottom - MIN_WIDTH;
                        } else {
                            tTop = parseMagnetVect(tTop);
                        }
                    }
                    break;
                    case BORDER_SELECT_TOP: {//shangzhong
                        tTop = top + dy;
                        if (tTop - topPadding < 0) {
                            tTop = topPadding;
                        } else if (tBottom - tTop < MIN_WIDTH) {
                            tTop = tBottom - MIN_WIDTH;
                        } else {
                            tTop = parseMagnetVect(tTop);
                        }
                    }
                    break;
                    case BORDER_SELECT_RIGHT_TOP: {
                        tRight = right + dx;
                        if (tRight >= frameWidth - rightPadding) {
                            tRight = frameWidth - rightPadding;
                        } else if (tRight - tLeft < MIN_WIDTH) {
                            tRight = tLeft + MIN_WIDTH;
                        } else {
                            tRight = parseMagnetHor(tRight);
                        }
                        tTop = top + dy;
                        if (tTop - topPadding < 0) {
                            tTop = topPadding;
                        } else if (tBottom - tTop < MIN_WIDTH) {
                            tTop = tBottom - MIN_WIDTH;
                        } else {
                            tTop = parseMagnetVect(tTop);
                        }
                    }
                    break;
                    case BORDER_SELECT_RIGHT: {//youzhong.................................
                        tRight = right + dx;
                        if (tRight >= frameWidth - rightPadding) {
                            tRight = frameWidth - rightPadding;
                        } else if (tRight - tLeft < MIN_WIDTH) {
                            tRight = tLeft + MIN_WIDTH;
                        } else {
                            tRight = parseMagnetHor(tRight);
                        }
                    }
                    break;
                    case BORDER_SELECT_RIGHT_BOTTOM: {
                        tRight = right + dx;
                        if (tRight >= frameWidth - rightPadding) {
                            tRight = frameWidth - rightPadding;
                        } else if (tRight - tLeft < MIN_WIDTH) {
                            tRight = tLeft + MIN_WIDTH;
                        } else {
                            tRight = parseMagnetHor(tRight);
                        }
                        tBottom = bottom + dy;
                        if (tBottom > frameHeight - bottomPadding) {
                            tBottom = frameHeight - bottomPadding;
                        } else if (tBottom - tTop < MIN_WIDTH) {
                            tBottom = tTop + MIN_WIDTH;
                        } else {
                            tBottom = parseMagnetVect(tBottom);
                        }
                    }
                    break;
                    case BORDER_SELECT_BOTTOM: {//xiazhong
                        tBottom = bottom + dy;
                        if (tBottom > frameHeight - bottomPadding) {
                            tBottom = frameHeight - bottomPadding;
                        } else if (tBottom - tTop < MIN_WIDTH) {
                            tBottom = tTop + MIN_WIDTH;
                        } else {
                            tBottom = parseMagnetVect(tBottom);
                        }
                    }
                    break;
                    case BORDER_SELECT_LEFT_BOTTOM: {
                        tLeft = left + dx;
                        if (tLeft - leftPadding < 0) {
                            tLeft = leftPadding;
                        } else if (tRight - tLeft < MIN_WIDTH) {
                            tLeft = tRight - MIN_WIDTH;
                        } else {
                            tLeft = parseMagnetHor(tLeft);
                        }
                        tBottom = bottom + dy;
                        if (tBottom > frameHeight - bottomPadding) {
                            tBottom = frameHeight - bottomPadding;
                        } else if (tBottom - tTop < MIN_WIDTH) {
                            tBottom = tTop + MIN_WIDTH;
                        } else {
                            tBottom = parseMagnetVect(tBottom);
                        }
                    }
                    break;
                    case BORDER_SELECT_MIDDLE: {
                        int width = right - left;
                        int height = bottom - top;

                        tLeft = left + dx;
                        tTop = top + dy;
                        tRight = right + dx;
                        tBottom = bottom + dy;
                        if (tLeft - leftPadding < 0) {
                            tLeft = leftPadding;
                            tRight = tLeft + width;
                        } else if (tRight > frameWidth - rightPadding) {
                            tRight = frameWidth - rightPadding;
                            tLeft = tRight - width;
                        } else {
                            tLeft = parseMagnetHor(tLeft);
                            tRight = tLeft + width;
                            if (!horLine.needDraw()) {
                                tRight = parseMagnetHor(tRight);
                                tLeft = tRight - width;
                            }
                            if (!horLine.needDraw()) {//尝试中心点捕捉
                                tLeft = parseMagnetHor(tLeft + width / 2) - width / 2;
                                tRight = tLeft + width;
                            }
                        }
                        if (tTop - topPadding < 0) {
                            tTop = topPadding;
                            tBottom = tTop + height;
                        } else if (tBottom > frameHeight - bottomPadding) {
                            tBottom = frameHeight - bottomPadding;
                            tTop = tBottom - height;
                        } else {
                            tTop = parseMagnetVect(tTop);
                            tBottom = tTop + height;
                            if (!vectLine.needDraw()) {
                                tBottom = parseMagnetVect(tBottom);
                                tTop = tBottom - height;
                            }
                            if (!vectLine.needDraw()) {
                                tTop = parseMagnetVect(tTop + height / 2) - height / 2;
                                tBottom = tTop + height;
                            }
                        }
                    }
                    break;
                    case BORDER_SELECT_NONE:
                    default:
                        return true;
                }
                currentSelectView.layout(tLeft, tTop, tRight, tBottom);
//                mLayers[selectIndex].setViewBound(
//                    new Bound(tLeft - leftPadding, tTop - topPadding, tRight - tLeft,
//                        tBottom - tTop));
                invalidate();
                TLog.e("move", "invalidate");
                break;
            case MotionEvent.ACTION_CANCEL:
            case MotionEvent.ACTION_UP:
                saveRequestLayout(currentSelectView);
                currentSelect = BORDER_SELECT_NONE;
                vectLine.reset();
                horLine.reset();
                setOutputSize(selectIndex,selectView);
                invalidate();
                TLog.e("up", "invalidate");
                break;
        }
        return true;
    }

    public void setOutputSize(int selectIndex,View view){
        Bound bound = new Bound();
        bound.x = view.getLeft();
        bound.y = view.getTop();
        bound.w = view.getWidth();
        bound.h = view.getHeight();
        Bound worldBound = BaseApp.toWorld(bound,frameWidth,frameHeight);
        BaseApp.send(CS0FLayerParam.createImageBounds(BaseApp.getSettings().getPVWConfig().getLayers()[selectIndex].getLayerType(),worldBound)).subscribe(cmd->{},e->{});
    }

    private float distance(float x, float y, float x1, float y1) {
        return (x - x1) * (x - x1) + (y - y1) * (y - y1);
    }

    private int motionEventSelect(float x, float y, View view) {
        if (view.getVisibility() == VISIBLE) {
            return motionEventSelect(x, y, view.getLeft(), view.getTop(), view.getRight(),
                    view.getBottom());
        }
        return BORDER_SELECT_NONE;
    }

    private int motionEventSelect(float x, float y, int left, int top, int right, int bottom) {
        float minDistance = Float.MAX_VALUE;
        int tempSelect = BORDER_SELECT_NONE;
        int width = right - left;
        int height = bottom - top;
        float points[][] = {{left, top + height / 2}, {left, top}, {left + width / 2, top},
                {right, top}, {right, top + height / 2}, {right, bottom}, {left + width / 2,
                bottom}, {left, bottom}};
        for (int i = 0; i < 8; i++) {
            float temp = distance(x, y, points[i][0], points[i][1]);
            if (temp < minDistance) {
                minDistance = temp;
                tempSelect = i;
            }
        }
        if (minDistance < radius * radius * 5) {//TODO 调整选择精准度
            return tempSelect;
        } else {
            //判断是否选择的是中间区域
            if (x > left && x < right && y > top && y < bottom) {
                return BORDER_SELECT_MIDDLE;
            }
        }
        return BORDER_SELECT_NONE;
    }

    public void saveRequestLayout(View sView) {
        int left, top, right, bottom;
        left = sView.getLeft();
        top = sView.getTop();
        right = sView.getRight();
        bottom = sView.getBottom();
        FrameLayout.LayoutParams layoutParams = (LayoutParams) sView.getLayoutParams();//new
        // FrameLayout.LayoutParams(margin);
        layoutParams.leftMargin = left;
        layoutParams.topMargin = top;
        layoutParams.width = right - left;
        layoutParams.height = bottom - top;
        sView.setLayoutParams(layoutParams);
    }

    public void swap(int srcPosition, int targetPosition,Layer srcLayer,Layer tarLayer) {
        for (int i = 0; i < getChildCount(); i++) {
            Layer layer = (Layer) getChildAt(i).getTag();
            String name = layer.getLayerType().name;
            TLog.e("test","beforeChange","i",i,"name",name);
        }
        if (srcPosition > targetPosition) {
            int temp = srcPosition;
            srcPosition = targetPosition;
            targetPosition = temp;
        }
        View srcView = getChildAt(srcPosition);
        View targetView = getChildAt(targetPosition);
        super.removeViewAt(targetPosition);
        super.removeViewAt(srcPosition);
        addView(targetView, srcPosition);
        addView(srcView, targetPosition);
        int count = srcPosition - targetPosition;
        for (int i = 0; i < Math.abs(count); i++) {
            BaseApp.send(CS0E_LayerInfo.upOrDownLayer(srcLayer,count < 0)).subscribe();
        }
        for (int i = 0; i < Math.abs(count); i++) {
            BaseApp.send(CS0E_LayerInfo.upOrDownLayer(tarLayer,count > 0)).subscribe();
        }
        for (int i = 0; i < getChildCount(); i++) {
            Layer layer = (Layer) getChildAt(i).getTag();
            String name = layer.getLayerType().name;
            TLog.e("test","AfterChange","i",i,"name",name);
        }
    }

    public void setChildFullScreenOrOldLocation(Layer layer, boolean isFull) {
        Layer[] layers = BaseApp.getSettings().getPVWConfig().getLayers();
        View view = getViewByLayer(layer);
        Bound oldBound;
        if (layer.getOldBound() != null) {
            oldBound = layer.getOldBound();
        } else {
            oldBound = new Bound(0, 0, 100, 100);// updata layer should save oldbound value
            layer.setOldBound(oldBound);
        }
        FrameLayout.LayoutParams layoutParams = (LayoutParams) view.getLayoutParams();
        if (isFull) {
            oldBound.x = view.getLeft() - leftPadding;
            oldBound.y = view.getTop() - topPadding;
            oldBound.w = view.getRight() - view.getLeft();
            oldBound.h = view.getBottom() - view.getTop();
            layoutParams.leftMargin = 0;
            layoutParams.topMargin = 0;
            layoutParams.width = frameWidth;
            layoutParams.height = frameHeight;
            layer.setViewBound(new Bound(0, 0, frameWidth, frameHeight));
        } else {
            layoutParams.leftMargin = oldBound.x;
            layoutParams.topMargin = oldBound.y;
            layoutParams.width = oldBound.w;
            layoutParams.height = oldBound.h;
        }
        view.setLayoutParams(layoutParams);
    }

    public void setChildVisible(Layer inputLayer, boolean isOpen) {
        View view =getViewByLayer(inputLayer);
        view.setVisibility(isOpen?VISIBLE:GONE);
        Layer layer = (Layer) view.getTag();//
        BaseApp.send(CS0E_LayerInfo.controlVisible(layer,isOpen)).subscribe();
        if (isOpen) {
            BaseApp.getLayer(layer.getLayerType()).subscribe(layer1->{
                BaseApp.getSettings().getPVWConfig().setLayer(layer1);
                view.setTag(layer1);
                Bound bound = BaseApp.toLocal(layer1.getViewBound(),getWidth(),getHeight());
                LayoutParams params = new LayoutParams(bound.w,bound.h);
                params.leftMargin = bound.x;
                params.topMargin = bound.y;
                view.setLayoutParams(params);
            },e->{});
        }
        invalidate();
    }

    boolean isLock = false;
    boolean isShowInfo = true;
    public void setLockLocation(boolean isLock){
        this.isLock = isLock;
        invalidate();
    }

    public void setShowInfo(boolean showInfo){
        isShowInfo = showInfo;
        invalidate();
    }

    private SparseArray<Rect> horArray = new SparseArray<>();
    private SparseArray<Rect> vectArray = new SparseArray<>();
    private int magnetThreshold = 6;
    private KeyValue horLine = new KeyValue(0);
    private KeyValue vectLine = new KeyValue(0);

    public void setSelectLayer(Layer selectLayer) {
        View view = getViewByLayer(selectLayer);
        setSelectView(view);
    }

    public View getViewByLayer(Layer inputLayer){
        View getView = null;
        for (int i = 0; i < getChildCount(); i++) {
            View view = getChildAt(i);
            Layer layer = (Layer) view.getTag();
            if(layer == inputLayer){
                getView = view;
                break;
            }
        }
        if(getView == null) throw new NullPointerException();//layer not set tag of layer
        return getView;
    }

    private static class KeyValue {

        int key;
        Rect rect;

        KeyValue(int key, int l, int t, int r, int b) {
            this.key = key;
            rect = new Rect(l, t, r, b);
        }

        KeyValue(int k) {
            this.key = k;
        }

        KeyValue(int k, Rect r) {
            key = k;
            rect = r;
        }

        void reset() {
            rect = null;
        }

        boolean needDraw() {
            return rect != null;
        }

    }


    private void initSparseArray() {
        if (currentSelect == BORDER_SELECT_NONE) {
            return;
        }
        horArray.clear();
        vectArray.clear();

        //增加布局捕捉
        Rect rect = new Rect(0, 0, frameWidth, frameHeight);
        horArray.put(leftPadding, rect);
        horArray.put(frameWidth - rightPadding, rect);
        horArray.put(leftPadding + (frameWidth - leftPadding - rightPadding) / 2, rect);
        vectArray.put(topPadding, rect);
        vectArray.put(frameHeight - bottomPadding, rect);
        vectArray.put(topPadding + (frameHeight - topPadding - bottomPadding) / 2, rect);

        for (int i = 0; i < getChildCount(); i++) {
            View view = getChildAt(i);
            if (view == getSelectView()) {
                continue;
            }
            Rect r = new Rect(view.getLeft(), view.getTop(), view.getRight(), view.getBottom());
            horArray.put(view.getLeft(), r);
            horArray.put(view.getRight(), r);
            if (horArray.get(i) == null) {
                horArray.put(view.getLeft() + view.getWidth() / 2, r);
            }

            vectArray.put(view.getTop(), r);
            vectArray.put(view.getBottom(), r);
            if (vectArray.get(i) == null) {
                vectArray.put(view.getTop() + view.getHeight() / 2, r);
            }
        }
    }

    private KeyValue findClosestValue(int val, SparseArray<Rect> array) {
        KeyValue keyValue = new KeyValue(val);
        int size = array.size();
        if (size == 0) {
            return keyValue;
        }
        int index = array.indexOfKey(val);
        if (index >= 0) {
            return keyValue;
        }
        index = ~index;
        if (index == 0) {
            int temp = array.keyAt(index);
            if (Math.abs(temp - val) < magnetThreshold) {
                keyValue.key = temp;
                keyValue.rect = array.valueAt(index);
                return keyValue;
            }
        } else if (index >= size) {
            int temp = array.keyAt(index - 1);
            if (Math.abs(temp - val) < magnetThreshold) {
                keyValue.key = temp;
                keyValue.rect = array.valueAt(index - 1);
                return keyValue;
            }
        } else {
            int temp = array.keyAt(index - 1);
            int temp2 = array.keyAt(index);
            if (val - temp > temp2 - val) {
                temp = temp2;
                index = index + 1;
            }
            if (Math.abs(temp - val) < magnetThreshold) {
                keyValue.key = temp;
                keyValue.rect = array.valueAt(index - 1);
                return keyValue;
            }
        }

        return keyValue;
    }

    private int parseMagnetVect(int vect) {
        vectLine = findClosestValue(vect, vectArray);
        return vectLine.key;
    }

    private int parseMagnetHor(int hor) {
        horLine = findClosestValue(hor, horArray);
        return horLine.key;
    }
}
